package com.vkl.admin;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

/**
 * Function链式调用工具类
 */
@Slf4j
public class FunctionChain<T, R> {

    private final List<ChainNode<?, ?>> chain = new ArrayList<>();

    private FunctionChain() {
    }

    public static <T, R> FunctionChain<T, R> start() {
        return new FunctionChain<>();
    }

    public <V> FunctionChain<T, R> then(Function<V, ?> function, ErrorStrategy<V> strategy) {
        chain.add(new ChainNode<>(function, strategy));
        return (FunctionChain<T, R>) this;
    }

    public R execute(T input) {
        Object current = input;
        for (ChainNode<?, ?> node : chain) {
            current = node.apply(current);
        }
        return (R) current;
    }

    private static class ChainNode<V, U> {
        private final Function<V, U> function;
        private final ErrorStrategy<V> strategy;

        public ChainNode(Function<V, U> function, ErrorStrategy<V> strategy) {
            this.function = function;
            this.strategy = strategy;
        }

        public Object apply(Object input) {
            try {
                return function.apply((V) input);
            } catch (Exception e) {
                return strategy.handle((V) input, e);
            }
        }
    }

    @FunctionalInterface
    public interface ErrorStrategy<V> {
        Object handle(V input, Exception e);
    }

    // 常用策略封装
    public static <V> ErrorStrategy<V> onErrorContinue() {
        return (input, e) -> {
            log.warn("步骤失败, 跳过. 输入值: {}", input, e);
            return input;
        };
    }

    public static <V> ErrorStrategy<V> onErrorBreak() {
        return (input, e) -> {
            log.error("步骤失败, 终止. 输入值: {}", input, e);
            throw new RuntimeException(e);
        };
    }

    public static <V> ErrorStrategy<V> onErrorFallback(Object fallback) {
        return (input, e) -> {
            log.warn("步骤失败, 回滚. 输入值: {}, 回滚值: {}", input, fallback, e);
            return fallback;
        };
    }

    public static <V> ErrorStrategy<V> onErrorThrow() {
        return (input, e) -> {
            throw new RuntimeException("链式调用发生异常：", e);
        };
    }

    public static void main(String[] args) {
        Function<String, String> trim = String::trim;
        Function<String, String> upper = String::toUpperCase;
        Function<String, String> validate = s -> {
            if (s.length() > 5) throw new IllegalArgumentException("Too long");
            return s;
        };
        Function<String, Integer> parse = Integer::parseInt;

        FunctionChain<Object, Object> chain = FunctionChain.start()
                .then(trim, onErrorContinue())
                .then(upper, onErrorBreak())
                .then(validate, onErrorFallback("DEFAULT"))
                .then(parse, onErrorFallback(0));

        Integer result = (Integer) chain.execute("   abcdefg   ");
        System.out.println(result);  // 输出 0，表示走了 fallback
    }
}